package com.durian.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.durian.config.ServiceException;
import com.durian.domain.DTO.ObsDefaultListDTO;
import com.durian.domain.DTO.ObsUserAddDTO;
import com.durian.domain.DTO.ObsUserLoginDTO;
import com.durian.domain.VO.ObsAddressListVO;
import com.durian.domain.VO.ObsUserListVO;
import com.durian.domain.VO.ObsUserLoginVO;
import com.durian.domain.entity.ObsAddress;
import com.durian.domain.entity.ObsUser;
import com.durian.enums.UserRoleSign;
import com.durian.mapper.ObsAddressMapper;
import com.durian.mapper.ObsUserMapper;
import com.durian.service.IObsUserService;
import com.durian.utils.BeanListUtils;
import com.durian.utils.JwtUtils;
import com.durian.utils.PageInfoResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author Durian
 * @since 2023-11-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ObsUserServiceImpl extends ServiceImpl<ObsUserMapper, ObsUser> implements IObsUserService {

    @Value("${default.pageNum}")
    private Integer pageNum;

    @Value("${default.pageSize}")
    private Integer pageSize;

    /**
     * 默认密码
     */
    private final String DEFAULT_PASSWORD = "123456";

    private final ObsUserMapper userMapper;

    private final ObsAddressMapper addressMapper;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public PageInfoResult<ObsUserListVO> listUser(ObsDefaultListDTO defaultListDTO) {

        String searchMessage = defaultListDTO.getSearchMessage();
        Integer pageNum = defaultListDTO.getPageNum();
        Integer pageSize = defaultListDTO.getPageSize();

        // 设置查询条件
        LambdaQueryWrapper<ObsUser> listUserWrapper = new LambdaQueryWrapper<ObsUser>()
                .like(StringUtils.isNotBlank(searchMessage), ObsUser::getUserName, searchMessage)
                .or(StringUtils.isNotBlank(searchMessage), i -> i
                        .like(ObsUser::getUserResume, searchMessage)
                        .like(ObsUser::getUserTel, searchMessage)
                );

        // 检查分页页码和大小
        if (ObjectUtils.isNull(pageNum)) {
            pageNum = this.pageNum;
        }
        if (ObjectUtils.isNull(pageSize)) {
            pageSize = this.pageSize;
        }

        // 分页查询
        PageInfo<ObsUser> pageInfo = PageHelper.startPage(pageNum, pageSize)
                .doSelectPageInfo(() -> userMapper.selectList(listUserWrapper));

        // 优化结果
        return PageInfoResult.of(pageInfo, user -> {
            // 新建user列表VO
            ObsUserListVO userListVO = new ObsUserListVO();
            // 将user复制到user列表VO中
            BeanUtils.copyProperties(user, userListVO);

            LambdaQueryWrapper<ObsAddress> listAddressWrapper = new LambdaQueryWrapper<ObsAddress>()
                    .eq(ObsAddress::getUserId, user.getUserId());
            // 获取用户的地址
            List<ObsAddress> addresses = addressMapper.selectList(listAddressWrapper);
            // 将用户的地址复制成VO
            List<ObsAddressListVO> addressList = BeanListUtils.copyListUtil(addresses, ObsAddressListVO.class);

            // 将地址列表放入对应的用户集合中
            userListVO.setAddressList(addressList);

            // 返回user列表VO
            return userListVO;
        });
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<ObsUserListVO> listUser() {
        List<ObsUser> obsUsers = userMapper.selectList(null);
        return BeanListUtils.copyListUtil(obsUsers, ObsUserListVO.class);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public ObsUserListVO getUser(Long userId) {
        ObsUserListVO user = new ObsUserListVO();
        LambdaQueryWrapper<ObsUser> userExistWrapper = new LambdaQueryWrapper<ObsUser>()
                .select(ObsUser::getUserId)
                .eq(ObsUser::getUserId, userId);
        if (!userMapper.exists(userExistWrapper)) {
            throw new ServiceException("用户不存在");
        }

        ObsUser obsUser = userMapper.selectById(userId);
        BeanUtils.copyProperties(obsUser, user);

        // 获取用户的地址
        LambdaQueryWrapper<ObsAddress> getAddressesWrapper = new LambdaQueryWrapper<ObsAddress>()
                .eq(ObsAddress::getUserId, userId);
        List<ObsAddress> address = addressMapper.selectList(getAddressesWrapper);
        // 转换用户地址的类型
        List<ObsAddressListVO> addresses = BeanListUtils.copyListUtil(address, ObsAddressListVO.class);

        user.setAddressList(addresses);

        return user;
    }

    @Override
    public ObsUser getUser(String userTel) {
        LambdaQueryWrapper<ObsUser> getUserWrapper = new LambdaQueryWrapper<ObsUser>()
                .eq(ObsUser::getUserTel, userTel);

        return userMapper.selectOne(getUserWrapper);
    }

    @Override
    public ObsUserLoginVO login(ObsUserLoginDTO userLogin) {

        String userTel = userLogin.getUserTel();
        String password = userLogin.getPassword();

        LambdaQueryWrapper<ObsUser> getUserWrapper = new LambdaQueryWrapper<ObsUser>()
                .eq(ObsUser::getUserTel, userTel);

        ObsUser user = userMapper.selectOne(getUserWrapper);
        if (ObjectUtils.isNull()) {
            throw new ServiceException("用户不存在！请先注册");
        }

        if (!user.getPassword().equals(password)) {
            throw new ServiceException("密码不正确");
        }

        ObsUserLoginVO obsUserLogin = new ObsUserLoginVO();
        BeanUtils.copyProperties(user, obsUserLogin);

        String token = JwtUtils.generateToken(user.getUserName(), user.getUserId());

        obsUserLogin.setToken(token);

        return obsUserLogin;
    }

    /**
     * 判断用户是否存在
     *
     * @param userId 用户id
     * @return true：存在； false：不存在
     */
    public Boolean userIsExist(Long userId) {

        LambdaQueryWrapper<ObsUser> userExistWrapper = new LambdaQueryWrapper<ObsUser>()
                .select(ObsUser::getUserId)
                .eq(ObsUser::getUserId, userId);
        return userMapper.exists(userExistWrapper);
    }

    @Override
    @Transactional
    public void resetPassword(Long userId) {

        // 检查用户是否存在
        if (!userIsExist(userId)) {
            throw new ServiceException("用户不存在！");
        }

        LambdaUpdateWrapper<ObsUser> updateUserWrapper = new LambdaUpdateWrapper<ObsUser>()
                .set(ObsUser::getPassword, DEFAULT_PASSWORD)
                .eq(ObsUser::getUserId, userId);
        int updateUser = userMapper.update(ObsUser.builder().build(), updateUserWrapper);

        if (updateUser != 1) {
            log.error("数据库未知：{} = userMapper.update({})", updateUser, updateUserWrapper.getSqlSet());
            throw new ServiceException("系统错误");
        }

    }

    @Override
    @Transactional
    public void userRegistration(ObsUserAddDTO userAddDTO) {

        String userTel = userAddDTO.getUserTel();

        // 获取用户信息
        ObsUser user = new ObsUser();
        BeanUtils.copyProperties(userAddDTO, user);

        // 检查手机号是否被注册
        this.checkPhone(userTel);

        // 判断密码是否为空，为空设为默认密码
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(DEFAULT_PASSWORD);
        }

        // 添加用户
        int addUser = userMapper.insert(user);
        if (addUser != 1) {
            log.error("数据库未知：{} = userMapper.insert()", addUser);
            throw new ServiceException("系统错误");
        }
    }

    @Override
    @Transactional
    public void updateUser(ObsUser user) {

        Long userId = user.getUserId();
        String userName = user.getUserName();
        String password = user.getPassword();
        String userResume = user.getUserResume();
        String userTel = user.getUserTel();
        String userAvatar = user.getUserAvatar();
        UserRoleSign userRoleSign = user.getUserRoleSign();

        // 检查用户是否存在
        if (!userIsExist(userId)) {
            throw new ServiceException("用户不存在！");
        }

        LambdaUpdateWrapper<ObsUser> updateUserWrapper = new LambdaUpdateWrapper<ObsUser>()
                .set(StringUtils.isNotBlank(userName), ObsUser::getUserName, userName)
                .set(StringUtils.isNotBlank(password), ObsUser::getPassword, password)
                .set(StringUtils.isNotBlank(userResume), ObsUser::getUserResume, userResume)
                .set(StringUtils.isNotBlank(userTel), ObsUser::getUserTel, userTel)
                .set(StringUtils.isNotBlank(userAvatar), ObsUser::getUserAvatar, userAvatar)
                .set(ObjectUtils.isNotNull(userRoleSign), ObsUser::getUserRoleSign, userRoleSign)
                .eq(ObsUser::getUserId, userId);

        // 更新用户信息
        int updateUSer = userMapper.update(new ObsUser(), updateUserWrapper);
        if (updateUSer != 1) {
            log.error("数据库未知：{} = userMapper.update({})", updateUSer, updateUserWrapper.getSqlSet());
            throw new ServiceException("系统错误");
        }

    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public void checkPhone(String phone) {
        LambdaQueryWrapper<ObsUser> userTelExistWrapper = new LambdaQueryWrapper<ObsUser>()
                .select(ObsUser::getUserId)
                .eq(ObsUser::getUserTel, phone);
        if (userMapper.exists(userTelExistWrapper)) {
            throw new ServiceException("该手机号已经注册！");
        }
    }

    @Override
    public void removeUser(List<Long> ids) {

        ids.forEach(id -> {
        });

    }
}
